// 加载 loading
import store from "../store"
import NProgress from "nprogress"
import {getRouters} from "../api/menu"
import {getToken, setToken} from "../utils/auth"
import {Message} from "element-ui"
import {PrevLoading} from "../utils/loading"
import router, {resetRouter, staticRoutes} from './index'
// /* Layout */
import Layout from '@/layout'
import ParentView from '@/layout/routerView/parent.vue'

PrevLoading.start()

// 多级嵌套数组处理成一维数组
export function formatFlatteningRoutes(arr) {
  if (arr.length <= 0) return false
  for (let i = 0; i < arr.length; i++) {
    if (arr[i].children) {
      arr = arr.slice(0, i + 1).concat(arr[i].children, arr.slice(i + 1))
    }
  }
  return arr
}

// 处理 tagsViewList 数据，默认路由全部缓存
// isKeepAlive 处理 `name` 值，进行路由缓存
export function formatTwoStageRoutes(arr) {
  if (arr.length <= 0) return false
  const newArr = []
  const cacheList = []
  arr.forEach((v) => {
    newArr.push({...v})
    // 默认路由全部缓存
    if (v.meta.isKeepAlive) {
      cacheList.push(v.name)
    }
    store.dispatch('keepAliveNames/setCacheKeepAlive', cacheList)
  })
  return newArr
}


// 缓存多级嵌套数组处理后的一维数组(tagsView、菜单搜索中使用：未过滤隐藏的(isHide))
export function setCacheTagsViewRoutes(arr) {
  // 先处理有权限的路由，否则 tagsView、菜单搜索中无权限的路由也将显示
  // 添加到 vuex setTagsViewRoutes 中
  // 获取默认路由
  let routes = formatFlatteningRoutes(arr.concat(staticRoutes[0].children))
  store.dispatch('tagsViewRoutes/setTagsViewRoutes', formatTwoStageRoutes(routes))
}

// 递归处理多余的 layout : <router-view>，让需要访问的组件保持在第一层 layout 层。
// 因为 `keep-alive` 只能缓存二级路由
// 默认初始化时就执行
export function keepAliveSplice(to) {
  if (to.matched && to.matched.length > 2) {
    to.matched.map((v, k) => {
      if (v.components.default instanceof Function) {
        v.components.default().then((components) => {
          if (components.default.name === 'parent') {
            to.matched.splice(k, 1)
            router.push({path: to.path, query: to.query})
            keepAliveSplice(to)
          }
        })
      } else {
        if (v.components.default.name === 'parent') {
          to.matched.splice(k, 1)
          keepAliveSplice(to)
        }
      }
    })
  }
}


// 遍历后台传来的路由字符串，转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
  return asyncRouterMap.filter((route) => {
    if (type && route.children) {
      route.children.forEach((c) => {
        c.path = route.path + '/' + c.path
      })
    }
    if (route.component) {
      // Layout  组件特殊处理
      if (route.component === 'Layout') {
        route.component = Layout
      } else if (route.component === 'ParentView') {
        route.component = ParentView
      } else {
        route.component = loadView(route.component)
      }
    }
    if (route.children != null && route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children, route, type)
    } else {
      delete route['children']
      delete route['redirect']
    }
    return true
  })
}


export const loadView = (view) => {
  if (process.env.NODE_ENV === 'development') {
    return (resolve) => require([`@/views/${view}`], resolve)
  } else {
    // 使用 import 实现生产环境的路由懒加载
    return () => import(`@/views/${view}`)
  }
}


// 延迟关闭进度条
export function delayNProgressDone(time = 300) {
  setTimeout(() => {
    NProgress.done()
  }, time)
}


// 动态加载后端返回路由路由
// 添加动态路由，`{ path: '*', redirect: '/404' }` 防止页面刷新，静态路由丢失问题
// next({ ...to, replace: true }) 动态路由 addRoute 完毕后才放行，防止刷新时 NProgress 进度条加载2次
// 文档地址：https://router.vuejs.org/zh/api/#router-addroutes
export function getRouterList(router, to, next) {
  resetRouter()
  getRouters().then((res) => {
    // 动态添加可访问路由表
    const rdata = JSON.parse(JSON.stringify(res.data))
    const accessRoutes = filterAsyncRouter(rdata, false, true)
    store.dispatch('routesList/setRoutesList', accessRoutes)
    setCacheTagsViewRoutes(JSON.parse(JSON.stringify(accessRoutes)))
    router.addRoutes(accessRoutes)
    router.addRoute({path: '*', redirect: '/404'})
    next({...to, replace: true})
  })
}

// 路由加载前
router.beforeEach((to, from, next) => {
  keepAliveSplice(to)
  NProgress.configure({showSpinner: false})
  // 处理给移动端使用的页面 如果url中携带了token的话 保存并允许访问页面
  if (to.query && to.query.token) {
    setToken(to.query.token)
    next()
    return
  }
  if (to.meta.title && to.path !== '/login') NProgress.start()
  if (getToken() && to.meta.requireLogin !== false) {
    /* has token*/
    if (to.path === '/login') {
      NProgress.start()
      next({path: '/'})
      delayNProgressDone()
    } else {
      if (store.getters.roles.length === 0) {
        // 判断当前用户是否已拉取完user_info信息
        store.dispatch('GetInfo').then(() => {
          getRouterList(router, to, next)
        }).catch((err) => {
          // store.dispatch('LogOut').then(() => {
          //   Message.error(err)
          //   next({path: '/'})
          // })
        })
      } else {
        next()
      }
    }
  } else {
    // 没有token
    if (to.meta.requireLogin === false) {
      // 在免登录白名单，直接进入
      next()
    } else {
      next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
      delayNProgressDone(0)
    }
  }
})


// 路由加载后
router.afterEach(() => {
  PrevLoading.done()
  delayNProgressDone()
})
